package com.aydx.minirpc.core.client;

import com.aydx.minirpc.core.MiniRpcContext;
import com.aydx.minirpc.core.MiniRpcException;
import com.aydx.minirpc.core.proxy.NodeInfo;
import com.aydx.minirpc.core.RemoteCallPackage;
import com.aydx.minirpc.core.register.NodeType;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * 远程调用中心
 */
public class RemoteCallCenter {
    private Logger logger = LoggerFactory.getLogger(RemoteCallCenter.class);
    private MiniRpcContext rpcContext;
    public RemoteCallCenter(MiniRpcContext rpcContext) {
        this.rpcContext=rpcContext;
    }

    public <T> T call(RemoteCallPackage remoteCallPackage, Class<T> resultType) throws KeeperException, InterruptedException {

        List<NodeInfo> nodeInfos=this.rpcContext.getRegisterCenter().getNodes(remoteCallPackage.getRegisterName(),NodeType.PROVIDER,remoteCallPackage.getInterfaceName(),remoteCallPackage.getGroup(),remoteCallPackage.getVersion());
        if(nodeInfos==null || nodeInfos.size()==0){
            throw new MiniRpcException("找不到生产者");
        }
        for(NodeInfo nodeInfo:nodeInfos){
            try{
                return remoteCall(remoteCallPackage,nodeInfo,resultType);
            }catch (Exception e){
                logger.info("节点{}:{}不可用，尝试下个节点",nodeInfo.getIp(),nodeInfo.getPort());
            }
        }
        //
        throw new MiniRpcException("无可用节点");
    }
    public <T> T remoteCall(RemoteCallPackage remoteCallPackage, NodeInfo nodeInfo,Class<T> resultType) throws Exception {
        NettyTcpClient nettyTcpClient=NettyTcpClient.build(nodeInfo.getIp(),nodeInfo.getPort(),1);
        NettyResoponseFuture future=nettyTcpClient.call(this.rpcContext.getSerializableFactory().serialize(remoteCallPackage));
        byte[] result=future.get();
        if(result==null && result.length==0){
            throw new MiniRpcException("服务器返回数据为空");
        }
        return this.rpcContext.getSerializableFactory().derialize(result,resultType);
    }
}
